<template>
    <div>
        <!-- 面包屑导航区 -->
        <el-breadcrumb separator-class="el-icon-arrow-right">
            <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
            <el-breadcrumb-item>权限管理</el-breadcrumb-item>
            <el-breadcrumb-item>角色列表</el-breadcrumb-item>
        </el-breadcrumb>
        <el-card>
            <!-- 搜索 添加 -->
            <el-row :gutter="20">
                <el-col :span="10">
                    <el-input placeholder="请输入内容" v-model="queryInfo.query" clearable @clear="getRolesList">
                        <el-button type="success" slot="append" icon="el-icon-search" @click="getRolesList"></el-button>
                    </el-input>
                </el-col>
                <el-col :span="13">
                    <el-button type="primary" @click="showAddRoleDialog" style="float:right">添加角色</el-button>
                </el-col>
            </el-row>
            <el-table :data="rolesList" border stripe :header-cell-style="table_header" empty-text="暂无数据">
                <!-- 展开列 -->
                <el-table-column type="expand">
                    <template slot-scope="scope">
                        <el-row
                                :class="['bdbottom', i1 === 0 ? 'bdtop' : '', 'vcenter']"
                                v-for="(item1, i1) in scope.row.children"
                                :key="item1.role_id">
                            <!-- 一级权限 -->
                            <el-col :span="5">
                                <el-tag closable @close="removeRightById(scope.row, item1, 1)">{{ item1.name}}</el-tag>
                                <i class="el-icon-caret-right"></i>
                            </el-col>
                            <!-- 二级和三级 -->
                            <el-col :span="19">
                                <!-- 通过for循环 渲染二级权限 -->
                                <el-row
                                        :class="[i2 === 0 ? '' : 'bdtop', 'vcenter']"
                                        v-for="(item2, i2) in item1.children"
                                        :key="item2.ID"
                                >
                                    <el-col :span="6 ">
                                        <el-tag
                                                type="success"
                                                closable
                                                @close="removeRightById(scope.row, item2, 2)"
                                        >{{ item2.name }}</el-tag>
                                        <i class="el-icon-caret-right"></i>
                                    </el-col>
                                    <el-col :span="18">
                                        <el-tag
                                                type="warning"
                                                v-for="(item3) in item2.children"
                                                :key="item3.ID"
                                                closable
                                                @close="removeRightById(scope.row, item3, 3)"
                                        >{{ item3.name}}</el-tag>
                                    </el-col>
                                </el-row>
                            </el-col>
                        </el-row>
                    </template>
                </el-table-column>
                <!-- 索引列 -->
                <el-table-column type="index" label="序号" width="50px" align="center"></el-table-column>
                <el-table-column label="角色名称" prop="role_name" align="center"></el-table-column>
                <el-table-column label="角色描述" prop="role_desc" align="center" min-width="150px"></el-table-column>
                <el-table-column label="创建时间" prop="created_at" align="center" min-width="120px">
                    <template slot-scope="scope">{{scope.row.created_at | datetimeFormat }}</template>
                </el-table-column>
                <el-table-column label="操作" width="300px" align="center">
                    <template slot-scope="scope">
                        <el-button type="primary" icon="el-icon-edit" size="mini" @click="showEditRoleDialog(scope.row)">编辑</el-button>
                        <el-button type="danger" icon="el-icon-delete" size="mini" @click="removeRoleById(scope.row)">删除</el-button>
                        <el-tooltip
                                class="item"
                                effect="dark"
                                content="分配权限"
                                :enterable="false"
                                placement="top"
                        >
                            <el-button
                                    type="warning"
                                    icon="el-icon-setting"
                                    size="mini"
                                    @click="showSetRightDialog(scope.row)"
                            >分配权限</el-button>
                        </el-tooltip>
                    </template>
                </el-table-column>
            </el-table>
        </el-card>
        <!-- 分页区域 -->
        <div class="pager-box">
            <el-pagination
                    @size-change="handleSizeChange"
                    @current-change="handleCurrentChange"
                    :current-page="queryInfo.pageNum"
                    :page-sizes="[2, 5, 10, 15]"
                    :page-size="queryInfo.pageSize"
                    layout="total, sizes, prev, pager, next, jumper"
                    prev-text="上一页"
                    next-text="下一页"
                    :total="total"
                    background
                    hide-on-single-page
            ></el-pagination>
        </div>

        <!-- 添加角色对话框 -->
        <el-dialog :title="Dialog_title" :visible.sync="RoleDialogVisible" width="40%" @close="resetForm('RoleFormRef')">
            <el-form
                    :model="RoleForm"
                    ref="RoleFormRef"
                    :rules="RoleFormRules"
                    label-width="100px"
            >
                <el-form-item label="角色名称" prop="role_name">
                    <el-input v-model="RoleForm.role_name"></el-input>
                </el-form-item>
                <el-form-item label="角色描述" prop="role_desc">
                    <el-input v-model="RoleForm.role_desc"></el-input>
                </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
                <el-button @click="RoleDialogVisible = false">取 消</el-button>
                <el-button type="primary" @click="AddOrUpdateRole">确 定</el-button>
            </span>
        </el-dialog>
        <el-dialog
            :visible.sync="setRightDialogVisible"
            width="50%"
            @close="setRightDialogClosed">
         <el-tabs v-model="activeName" type="card" @tab-click="handleClick" style="margin-top: -20px">
                <el-tab-pane label="菜单权限" name="menu">
                    <el-tree
                            :data="rightsList"
                            :props="treeProps"
                            ref="treeRef"
                            show-checkbox
                            node-key="ID"
                            default-expand-all
                            :default-checked-keys="defKeys"
                    ></el-tree>
                </el-tab-pane>
                <el-tab-pane label="Api权限" name="api">
                    <el-tree
                            :data="apiList"
                            :props="ApitreeProps"
                            ref="ApitreeRef"
                            show-checkbox
                            node-key="onlyId"
                            default-expand-all
                            :default-checked-keys="ApidefKeys"
                    ></el-tree>
                </el-tab-pane>
            </el-tabs>
            <span slot="footer" class="dialog-footer">
                <el-button @click="setRightDialogVisible = false">取 消</el-button>
                <el-button type="primary" @click="allotRights">确 定</el-button>
            </span>
        </el-dialog>
<!--        <el-dialog-->
<!--        title="分配权限"-->
<!--        :visible.sync="setRightDialogVisible"-->
<!--        width="50%"-->
<!--        @close="setRightDialogClosed"-->
<!--        >-->
<!--            <el-tree-->
<!--                    :data="rightsList"-->
<!--                    :props="treeProps"-->
<!--                    ref="treeRef"-->
<!--                    show-checkbox-->
<!--                    node-key="ID"-->
<!--                    default-expand-all-->
<!--                    :default-checked-keys="defKeys"-->
<!--            ></el-tree>-->
<!--            <span slot="footer" class="dialog-footer">-->
<!--                    <el-button @click="setRightDialogVisible = false">取 消</el-button>-->
<!--                    <el-button type="primary" @click="allotRights">确 定</el-button>-->
<!--                </span>-->
<!--        </el-dialog>-->
    </div>
</template>
<script>
    import Qs from 'qs'

    export default {
        data () {
            return {
                queryInfo: {
                    query: '',
                    // 当前页数
                    pageNum: 1,
                    // 每页显示多少数据
                    pageSize: 10,
                },
                total: 0,
                // 所有角色列表
                rolesList: [],
                // 分配权限框
                setRightDialogVisible: false,
                activeName: 'menu',
                // 权限列表
                rightsList: [],
                apiList: [],
                //  树形控件的属性绑定对象
                treeProps: {
                    label: 'name',
                    children: 'children'
                },
                ApitreeProps: {
                    label: 'description',
                    children: 'children'
                },
                //   默认选中节点ID值
                defKeys: [],
                ApidefKeys: [],

                Dialog_title: '',
                Dialog_state: '',
                //   添加用户对话框
                RoleDialogVisible: false,
                // 添加角色表单
                RoleForm: {},
                //   添加角色表单验证
                RoleFormRules: {
                    role_name: [
                        { required: true, message: '请输入角色名称', trigger: 'blur' }
                    ],
                    role_desc: [
                        { required: true, message: '请输入角色描述', trigger: 'blur' }
                    ]
                },
                //   当前即将分配权限的Id
                roleId: 0
            }
        },
        created () {
            this.getRolesList();
        },
        methods: {
            handleClick(value){
                console.log(value.name);
            },
            table_header(row, column, rowIndex, columnIndex){
                return 'background-color: rgb(102,177,255);color: white;font-size:14px;'
            },
            // 监听 pagesize改变的事件
            handleSizeChange (newSize) {
                // console.log(newSize)
                this.queryInfo.pageSize = newSize
                this.getRolesList()
            },
            // 监听 页码值 改变事件
            handleCurrentChange (newSize) {
                this.queryInfo.pageNum = newSize;
                this.getRolesList()
            },
            resetForm(formName){
                this.RoleForm = {};
                if (this.$refs[formName] !== undefined) {
                    this.$refs[formName].resetFields();
                }
            },
            // 权限对话框关闭事件
            setRightDialogClosed () {
                this.setRightDialogVisible = false;
                this.defKeys = [];
                this.ApidefKeys = [];
                this.activeName = 'menu';
            },
            showAddRoleDialog(){
                this.Dialog_state = 'add';
                this.Dialog_title = "添加角色";
                this.RoleDialogVisible = true
            },
            showEditRoleDialog(role){
                this.RoleForm = JSON.parse(JSON.stringify(role));
                this.Dialog_state = 'edit';
                this.Dialog_title = "编辑角色";
                this.RoleDialogVisible = true
            },
            // 分配权限
            async showSetRightDialog (role) {
                this.roleId = role.role_id;

                const { data: res, status: status } = await this.axios.get('menus/getAllMenuTree');
                if (status !== 200) {
                    return this.$message.error('获取权限数据失败！')
                }
                this.rightsList = res.data.menus;
                this.defKeys = [];
                this.getLeafkeys(role, this.defKeys);

                const { data: res1, status: status1 } = await this.axios.get('api/getApiTree', {params: {"role_id": this.roleId}});
                if (status1 !== 200) {
                    return this.$message.error('获取Api数据失败！')
                }
                this.apiList = res1.data.api_list;
                this.ApidefKeys = res1.data.ApidefKeys;

                this.setRightDialogVisible = true;
            },
            // async getApiTree2(){
            //     const { data: res2, status: status2 } = await this.axios.get('api/getApiList');
            //     if (status2 !== 200) {
            //         return this.$message.error('获取Api数据失败！')
            //     }
            //     this.apiList = this.buildApiTree(res2.data.apis);
            //     const { data: res1, status: status1 } = await this.axios.get('casbin/getPolicyPathByRoleId', {params: {"role_id": this.roleId.toString()}});
            //     if (status1 !== 200) {
            //         return this.$message.error('获取角色Api数据失败！')
            //     }
            //     this.ApidefKeys = [];
            //     res1.data&&res1.data.map(item=>{
            //         this.ApidefKeys.push("p:"+item.path+"m:"+item.method)
            //     });
            // },
            // // 创建api树方法
            // buildApiTree(apis) {
            //     const apiObj = {};
            //     apis && apis.map(item => {
            //         item.onlyId = "p:"+item.path+"m:"+item.method;
            //         if (apiObj.hasOwnProperty(item.apiGroup)) {
            //             apiObj[item.apiGroup].push(item)
            //         } else {
            //             Object.assign(apiObj, { [item.apiGroup]: [item] })
            //         }
            //     });
            //     const apiList = [];
            //     for (const key in apiObj) {
            //         const treeNode = {
            //             ID: key,
            //             description: key + '组',
            //             children: apiObj[key]
            //         };
            //         apiList.push(treeNode)
            //     }
            //     return apiList
            // },

            // 通过递归 获取角色下三级权限的 id, 并保存到defKeys数组
            getLeafkeys (node, arr) {
                // 没有children属性，则是三级节点
                if (!node.children) {
                    return arr.push(node.ID)
                }
                node.children.forEach(item => this.getLeafkeys(item, arr))
            },

            async getRolesList() {
                const { data: res, status: status } = await this.axios.get('roles/getAllRoleMenuTree', {params: this.queryInfo})
                if (status !== 200) {
                    return this.$message.error('获取角色列表失败！')
                }
                this.rolesList = res.data.roles;
                this.queryInfo.total = res.data.total
            },

            // 添加或更新角色Add
            AddOrUpdateRole () {
                if (this.Dialog_state === 'add') {
                    this.$refs.RoleFormRef.validate(async valid => {
                        if (!valid) return;
                        const {data: res, status: status} = await this.axios.post('roles/addOneRole', this.RoleForm);
                        if (status !== 201) {
                            this.$message.error('添加角色失败！')
                        }
                        this.$message.success('添加角色成功！')
                        this.getRolesList();
                        this.RoleDialogVisible = false;
                    });
                }else {
                    this.$refs['RoleFormRef'].validate(async valid => {
                        // console.log(valid)
                        // 表单预校验失败
                        if (!valid) return;
                        const {data: res, status: status} = await this.axios.put('roles/updateRole', this.RoleForm);
                        if (status !== 200) {
                            this.$message.error('更新角色信息失败！')
                        }
                        // 隐藏编辑角色对话框
                        this.$message.success('更新角色信息成功！');
                        this.getRolesList();
                        this.RoleDialogVisible = false;
                    })
                }
            },

            // 删除角色
            async removeRoleById (role) {
                const confirmResult = await this.$confirm(
                    '此操作将永久删除角色 ' + role.role_name +  ',  是否继续?',
                    '提示',
                    {
                        confirmButtonText: '确定',
                        cancelButtonText: '取消',
                        type: 'warning'
                    }
                ).catch(err => err)
                if (confirmResult !== 'confirm') {
                    return this.$message.info('已取消删除')
                }
                const { data: res, status: status } = await this.axios.delete('roles/deleteRole', {params: {"role_id": role.role_id}})
                if (status !== 200) return this.$message.error('删除角色失败！')
                this.$message.success('删除用户成功！')
                this.getRolesList()
            },

            // 根据ID删除对应的权限
            async removeRightById (role, item, level) {
                let menu_ids = [item.ID];
                if (item.children){
                    var arr = item.children
                    for(var j = 0,len=arr.length; j < len; j++) {
                        menu_ids.push(arr[j].ID)
                    }
                }
                // 弹框提示 删除
                const confirmResult = await this.$confirm(
                    '此操作将永久删除该权限, 是否继续?',
                    '提示',
                    {
                        confirmButtonText: '确定',
                        cancelButtonText: '取消',
                        type: 'warning'
                    }
                ).catch(err => err)
                // 点击确定 返回值为：confirm
                // 点击取消 返回值为： cancel
                if (confirmResult !== 'confirm') {
                    this.$message.info('已取消权限删除')
                    return
                }
                const { data: res, status: status } = await this.axios.delete(
                    `roles/deleteRoleRight`, {params: {"role_id": role.role_id, "menu_ids": menu_ids.join('-')}}
                )
                if (status !== 200) {
                    return this.$message.error('删除权限失败！')
                }
                role.children = res.data
                this.$message.success('删除权限成功！')
            },

            // 分配权限确定
            async allotRights () {
                if (this.activeName === 'menu') {
                    // 获得当前选中和半选中的Id
                    const keys = [
                        ...this.$refs.treeRef.getCheckedKeys(),
                        ...this.$refs.treeRef.getHalfCheckedKeys()
                    ];
                    // join() 方法用于把数组中的所有元素放入一个字符串
                    const idStr = keys.join(',');
                    const {status: status} = await this.axios.put(`roles/allotMenus`, Qs.stringify({
                        menu_ids: idStr,
                        role_id: this.roleId
                    }));
                    if (status !== 200) { return this.$message.error('分配权限失败！') }
                }else if (this.activeName === 'api'){
                    // 获得当前选中和半选中的Id
                    const checkArr = this.$refs.ApitreeRef.getCheckedNodes(true);
                    var casbinInfos = [];
                    checkArr&&checkArr.map(item=>{
                        var casbinInfo = {path:item.path, method:item.method};
                        casbinInfos.push(casbinInfo)
                    });
                    const {status: status} = await this.axios.post(`casbin/updateCasbin`, {role_id: this.roleId.toString(), casbinInfos});
                    if (status !== 200) { return this.$message.error('分配权限失败！') }
                }
                this.$message.success('分配权限成功!');
                this.getRolesList();
                this.setRightDialogVisible = false
            }
        }
    }
</script>
<style lang="less"scoped>
    .el-tag {
        margin: 7px;
    }
    .bdtop {
        border-top: 1px solid #eee;
    }
    .bdbottom {
        border-bottom: 1px solid #eee;
    }
    .vcenter {
        display: flex;
        align-items: center;
    }
</style>